package com.omnisyr.textrebuilder.util;

import java.util.Comparator;
import java.util.Iterator;

import com.omnisyr.textrebuilder.util.structure.SimpleArrayList;
import com.omnisyr.textrebuilder.util.structure.SimpleTreeMap;

public class Counter<T> implements Iterable<CounterNode<T>> {

	private SimpleArrayList<CounterNode<T>> list;
	private SimpleTreeMap<CounterNode<T>, Integer> map;
	private Comparator<CounterNode<T>> comparator;

	public Counter(Comparator<T> comparator) {

		this.comparator = (a, b) -> comparator.compare(a.get(), b.get());
		this.map = new SimpleTreeMap<CounterNode<T>, Integer>(this.comparator);
		this.list = new SimpleArrayList<CounterNode<T>>();

	}

	public void add(T t) {

		CounterNode<T> node = new CounterNode<T>(t);
		Integer count = this.map.get(node);

		if (count == null) {

			this.list.add(node);
			this.map.add(node, 1);

			return;

		}

		this.map.add(node, ++count);

	}

	public void build() {

		for (int i = 0; i < this.list.size(); i++) {

			this.list.get(i).setCount(this.map.get(this.list.get(i)));

		}

		this.list.sort((a, b) -> Integer.compare(b.count(), a.count()));

		this.map = null;

	}

	public int size() {

		return this.list.size();

	}

	public CounterNode<T> get(int index) {

		return this.list.get(index);

	}

	@Override
	public Iterator<CounterNode<T>> iterator() {

		return new SimpleIterator();

	}

	private class SimpleIterator implements Iterator<CounterNode<T>> {

		private int index;

		@Override
		public boolean hasNext() {

			return this.index < list.size();

		}

		@Override
		public CounterNode<T> next() {

			return list.get(this.index++);

		}

	}

}
